
local skynet = require "skynet"
local log = require "Log"
local msgpack = require "msgpack_helper"
local ltime = require 'ltime'
local config = require "configquery"
local json = require "cjson"
local NodeMessage = require "NodeMessage"

require "util"

local User = class("User")

---------------------------------------------------------
-- Private
---------------------------------------------------------
function User:ctor(message)
	self.userList = {}	
	self.nodename = skynet.getenv("svr_id")
	self.nodeMessage = NodeMessage.new()
	self.msg = message
	--物品id
	self.tbGoodsName = {
		uchip = 1,
		udiamond = 2,
		room_ticket = 3,
	}

	self:register()
end

function User:register()
	local msg = self.msg
	--服务器发来的
	msg:registerOper("get_user",handler(self,self.getUser))
	msg:registerOper("get_user_info",handler(self,self.getUserInfo))
	msg:registerOper("get_user_table",handler(self,self.getUserTable))
	msg:registerOper("get_money",handler(self,self.getMoney))
	msg:registerOper("change_money",handler(self,self.changeMoney))
	msg:registerOper("add_rmb",handler(self,self.addRmb))
	msg:registerOper("reduce_rmb",handler(self,self.reduceRmb))
	msg:registerOper("update_tableid",handler(self,self.updateTableid))
	msg:registerOper("safe_close",handler(self,self.safeClose))
	msg:registerOper("web_change_money",handler(self,self.webChangeMoney))
	msg:registerOper("web_change_money2",handler(self,self.webChangeMoney2))
	msg:registerOper("rb_change_money",handler(self,self.robotChangeMoney))
	msg:registerOper("change_fangka",handler(self,self.changeFangka))
	

end
---------------------------------------------------------
-- Public
---------------------------------------------------------
function User:getUserList()
	return self.userList
end

--把玩家信息变更推送到游戏中
function User:updateInfoToGame(user, data)
	if not user then
		--log.error('update_player_to_game user is nil') 
		return
	end
	local tableid = user.tableid
	local playerid = user.playerid
	if tableid > 0 then
		print("======================================》", tableid)
		self.nodeMessage:sendTable(tableid,'update_prop',playerid,data)
	end
end

--islogin 登入
function User:getUser(playerid, islogin)
	local user = self.userList[playerid]
	if islogin then
		if user then --断线后重登进来
			user.user_info = calldb('reload_role',playerid)
			-- print("____user",user)
			return user
		end		
		user = { playerid = playerid }
		user.tableid = 0	
		user.user_info = calldb('get_role',playerid) --取usergame表数据
		--userinfo表	
		local sql = string.format("select * from userinfo where uid=%d",playerid)	
		local infoRes = self.nodeMessage:callService("mysql_service","execute",sql)
		-- user.userInfoEx = calldb('reload_userinfo',playerid)	
		user.userInfoEx = {}	
		if next(infoRes) and next(infoRes[1])then	
			user.userInfoEx = infoRes[1]
		end
		if not user.user_info or not next(user.user_info) then --帐号不存在，不给进入大厅
			log.error("___帐号不存在，不给进入大厅"..playerid)
			return nil
		end
		self.userList[playerid] = user		
	end

	return user
end

--重新加载玩家信息
function User:setUserInfo(playerid)	
	if not self.userList[playerid] then
		log.debug("_______setUserInfo_____self.userList___________空")
		return 
	end 	
	calldb('unload_role',playerid)
	local userInfo = calldb('reload_role',playerid)

	self.userList[playerid].user_info = userInfo
	return true
end

--取玩家信息
function User:getUserInfo( playerid )
	local user = self.userList[playerid]
	local info
	if user and user.user_info then
		info = user.user_info
	else
		info = calldb('get_role',playerid)
	end
	return info
end

--给指定玩定发消息,,,,
function User:notice(playerid, msg)
	local user = self.userList[playerid]
	if user and user.u_info then
		local tp = type(msg)
		if tp == 'string' then
			msg = { msg_text = msg }
			log.debug(msg)
			msgpack.send_message(user.u_info.fd, user.u_info.contype, 'notice_text',msg)
		elseif tp == 'table' then
			log.debug(json.encode(msg))
			for k,v in pairs(msg) do				
				msgpack.send_message(user.u_info.fd, user.u_info.contype, k, v)
			end
		end
	end
end

--登出
function User:logout(playerid, msg, err)
	if playerid then
		 local user = self.userList[playerid]
		 local tableObj = g_objects:getOne('Table')
		 if user then
		 	--通知桌子玩家离线
		 	tableObj:disconnect(playerid, user.tableid)
		 	--user.tableid = 0
		 end
		if msg and not err then
			self:notice(playerid, msg)
		end
	end
end

--断线
function User:disconnect(playerid, msg, err)
	if not playerid then
		return
	end
	 local user = self.userList[playerid]
	 local tableObj = g_objects:getOne('Table')
	 if user then
	 	--通知桌子玩家离线
	 	tableObj:disconnect(playerid, user.tableid)

	 	--更新机器人离线表
	 	if playerid < 5000000 then 
			local data = {uid=playerid,online=0}	
			senddb('update_robot_online',data)		
			data = {playerid=playerid,online=0}
			self.nodeMessage:sendGlobalService('robot_service','rb_nt_offline',data) 
		end	
	 end
	-- if msg and not err then
	-- 	self:notice(playerid, msg)
	-- end
	
end


--登录后进入大厅
function User:enterGate(u_info, playerid, redirect,rebot)
	local other_service --是否已登录，异地登录
	local fd = u_info.fd
	local redirect = redirect
	if not redirect then
		-- other_service = g_handler.CMD.check_user_enter(fd, playerid) 
		--异地登录把之前登录者踢下线		
		other_service = self.nodeMessage:callService('.proxy', 'check_user_enter',skynet.self(), fd, playerid)
	end

	if not other_service or other_service == skynet.self() then
		local res 
		self:setUserInfo(playerid)

		local user = self:getUser(playerid, true)		
		if not user then --玩家不存在
			log.debug("______error________self:enterGate"..playerid)
			return false
		end
		user.rebot = rebot--机器人
		user.playerid = playerid
		user.u_info = u_info 
		u_info.user = user
		u_info.playerid = playerid		

		--金币不足先自动加点
		-- print("_______enter gate___",playerid,user.user_info.uchip,user.user_info.room_ticket)
		-- if user.user_info.uchip < 200 then 
		-- 	self:changeMoney(playerid,50000)
		-- end
		-- if user.user_info.room_ticket < 100 then 
		-- 	self:changeFangka(playerid,5000)
		-- end		
		
		local logoutObj = g_objects:getOne('Logout')
		logoutObj:cut(playerid)
		local ntData = {
			nt_enter_gate = {
				addr = 0,				
			}
		}		
		if user.tableid and user.tableid > 0 then 
			--玩家还在游戏中,回到指定的房间			
			ntData.nt_enter_gate = {
				addr = 1,
				info = {tableid=user.tableid,gameid=getGameIdbyTable(user.tableid)}
			}
		end
		if ntData.nt_enter_gate and ntData.nt_enter_gate.addr == 0 then
			local sql = string.format("delete from user_online where uid = %d;", playerid)
			skynet.call("mysql_service", "lua", "execute", sql)
		end
		self:notice(playerid,ntData)
		self.nodeMessage:sendGlobal('set_user_info',playerid,{nodename=self.nodename})
		if playerid < 5000000 then 
			local data = calldb('reload_robot_online',playerid)
			print("______update_robot_online__",playerid,data)
			if data and next(data) then 
				data = {uid=playerid,online=1}	
				senddb('update_robot_online',data)	
				data = {playerid=playerid,online=1}
				self.nodeMessage:sendGlobalService('robot_service','rb_nt_online',data) 
			end
		end
		
		user.login_time = os.date("%Y-%m-%d %H:%M:%S", os.time())

		return true
	else
		log.debug("______重新登录____redirect____")
		redirect = true
		local info = {
			fd = u_info.fd,
			gate = u_info.gate,
			contype = u_info.contype,
			addr = u_info.addr,
			sid = u_info.sid,
		}
		--把当前服务的agent清除
		-- self.user_agents[fd] = nil
		if not self.command then 
			self.command = g_objects:getOne('Command')
		end
		self.command:removeUserAgent(fd)

		skynet.send(other_service,'lua', 'redirect', info, redirect,playerid)

	end
	return true
end


---------------------------------------------------------
-- OPER
---------------------------------------------------------


--取玩家所在桌子
function User:getUserTable(playerid)
	local user = self:getUser(playerid)
	if user then 
		return user.tableid
	end
	return 0
end

function User:getMoney( playerid )
	if not playerid then return 0 end
	local user_info
	local tp = type(playerid)
	if tp == 'number' then
		user_info = self:getUserInfo(playerid)
	end
	if not user_info then return 0 end
	return user_info.uchip
end

--playerid玩家ID，money增加的金币，reason理由，
function User:changeMoney( playerid, money, reason)
	-- print("________reason___",reason)
	log.debug("_____changeMoney_________"..playerid.." ".. money,reason)
	if not playerid then return false end
	-- if money<0 then return false end
	-- if money==0 then return true end
	local userInfo, user
	local before
	userInfo = self:getUserInfo(playerid)
	user = self:getUser(playerid)
	if not userInfo then
		--玩家信息不存在
		print("error_____changeMoney____########无玩家信息 不能出现这种情况#",playerid,money)
		return false 
	end
	if money ~= 0 then 
		--重新加载玩家信息
		self:setUserInfo(playerid)	
		userInfo = self:getUserInfo(playerid)
		before = userInfo.uchip		
		local change = userInfo.uchip + money
		if change < 0 then 
			print("error_____changeMoney____#######钱不够赔, 不能出现这种情况#",playerid,money)
			return false
		end
		userInfo.uchip = change
		--更新到数据库
		local data = {uid=playerid,uchip=userInfo.uchip}	
		senddb('update_role',data,true)	
		--发送到客户端	
		local tbGood = {{id = self.tbGoodsName.uchip, num = tostring(userInfo.uchip) }}
		local data = {
			nt_goods_change = {goods=tbGood}
		}
		self:notice(playerid,data)
	end
	--流水记录写到
	if reason then 
		local tableName = 'coinlog'.. os.date("%Y%m%d", os.time())
		local str = tableName .." (uid,changecoin,time,code,moneytype,game,gameid,gametype)"
		local sql = string.format("insert into %s value(%d,%d,%d,%d,%d,%d,%d,%d)",str,playerid,money,os.time(),reason.code,reason.moneytype,reason.game,reason.gameid,reason.gametype)
		skynet.send("mysql_log", "lua", "execute", sql)
	end

	return userInfo.uchip
end

--修改房卡
function User:changeFangka( playerid, money, reason)

	log.debug("_____changeFangka_________"..playerid.." ".. money,reason)
	if not playerid then return false end
	local userInfo, user
	local before
	userInfo = self:getUserInfo(playerid)
	-- user = self:getUser(playerid)
	if not userInfo then
		--玩家信息不存在
		print("error_____changeFangka____########无玩家信息 不能出现这种情况#",playerid,money)
		return false 
	end
	if money ~= 0 then 
		--重新加载玩家信息
		self:setUserInfo(playerid)	
		userInfo = self:getUserInfo(playerid)
		-- before = userInfo.uchip		
		local change = userInfo.room_ticket + money
		if change < 0 then 
			print("error_____changeFangka____#######房卡不够赔, 不能出现这种情况#",playerid,money)
			return false
		end
		userInfo.room_ticket = change
		--更新到数据库
		local data = {uid=playerid,room_ticket=userInfo.room_ticket}	
		senddb('update_role',data,true)	
		--发送到客户端	
		local tbGood = {{id = self.tbGoodsName.room_ticket, num = tostring(userInfo.room_ticket) }}
		local data = {
			nt_goods_change = {goods=tbGood}
		}
		self:notice(playerid,data)
	end
	-- --流水记录写到
	-- if reason then 
	-- 	local tableName = 'coinlog'.. os.date("%Y%m%d", os.time())
	-- 	local str = tableName .." (uid,changecoin,time,code,moneytype,game,gameid,gametype)"
	-- 	local sql = string.format("insert into %s value(%d,%d,%d,%d,%d,%d,%d,%d)",str,playerid,money,os.time(),reason.code,reason.moneytype,reason.game,reason.gameid,reason.gametype)
	-- 	skynet.send("mysql_log", "lua", "execute", sql)
	-- end

	return userInfo.room_ticket
end

--增加银币
function User:addRmb( playerid, rmb, reason)
	
	if rmb<=0 then return false end
	local userInfo, user
	userInfo = self:getUserInfo(playerid)
	user = self:getUser(playerid)
	if not userInfo then
		print("error_2_____addRmb___########无玩家信息 不能出现这种情况#",playerid,rmb)
		return false 
	end
	userInfo.udiamond = userInfo.udiamond + rmb
	local data = {uid=playerid,udiamond=userInfo.udiamond}	
	senddb('update_role',data)		
	local tbGood = {{id = self.tbGoodsName.udiamond, num = tostring(userInfo.udiamond) }}
	local data = {
		nt_goods_change = {goods=tbGood}
	}
	self:notice(playerid,data)		

	return true,userInfo.udiamond
end

--减少银币
function User:reduceRmb( playerid, rmb , reason)
	if rmb<=0 then return false end
	local userInfo, user
	userInfo = self:getUserInfo(playerid)
	user = self:getUser(playerid)
	if not userInfo then
		print("error_2_____reduceRmb___########无玩家信息 不能出现这种情况#",playerid,rmb)
		return false 
	end
	local udiamond = userInfo.udiamond - rmb
	if udiamond < 0 then 
		print("error_3_____reduceRmb___########silver<0 不能出现这种情况#",playerid,rmb,userInfo.silver)
	end
	userInfo.udiamond = udiamond
	local data = {uid=playerid,udiamond=userInfo.udiamond}	
	senddb('update_role',data)		
	local tbGood = {{id = self.tbGoodsName.udiamond, num = tostring(userInfo.udiamond) }}
	local data = {
		nt_goods_change = {goods=tbGood}
	}
	self:notice(playerid,data)	

	return true,userInfo.udiamond
end


--清除玩家信息
function User:clear(playerid)
	local user = self.userList[playerid]
	if user and user.user_info and user.user_info.online == 1 then 
		--在线不要清除
		return false 
	end
	self.userList[playerid] = nil
	calldb('unload_role',playerid)
	return true
end

--踢出
function User:kickPlayer(playerid,msg)
	local content = '您已被封号，如有疑问请联系管理员.'
	if not msg then
		content = msg
	end
	local user = self.userList[playerid]
	if not user then 
		print("___玩家信息不存在__")
		return 
	end
	local data =  {nt_kick_player={
		playerid = playerid,
		content = content,
	}}
	self:notice(playerid,data)
	--踢出
	-- self.nodeMessage:sendService('.proxy', 'logout',playerid)
	if not user.u_info then 
		return 
	end
	self.nodeMessage:sendService('.proxy','kick_player',user.u_info.fd)
	print("_____完成封号踢下线__",playerid)
end

--人数
function User:setPlayerNum(add)
	-- if add then 
	--     --游戏人数增加
	-- 	local tb = call_redis({ "hgetall", "online" }, 1)	
	-- 	local num = tb.playing or 0
	-- 	num = tonumber(num)
	-- 	send_redis({ "hmset", "online", {playing=num+1} }, 1)
	-- 	return
	-- end
	-- --游戏人数减少
	-- local tb = call_redis({ "hgetall", "online" }, 1)	
	-- local num = tb.playing or 0
	-- num = tonumber(num)
	-- send_redis({ "hmset", "online", {playing=num-1} }, 1)

end


--设置用户桌子id
function User:updateTableid( playerid, tableid)
	print('______#############_______playerid_____tableid___________',playerid,tableid)
	if not playerid then return false end 
	local user = self:getUser(playerid)
	if not user then
		return false
	end		
	if not tableid or tableid == 0 then 
		-- self:setPlayerNum(false)
		--离桌

	elseif tableid ~= user.tableid then 
		-- self:setPlayerNum(true)
	end
	self.userList[playerid].tableid = tableid
	if playerid < 5000000 then 
		local data = {uid=playerid,tableid=tableid}	
		senddb('update_robot_online',data)
		data = {playerid=playerid,tableid=tableid}
		self.nodeMessage:sendGlobalService('robot_service','rb_nt_online',data) 
	end
	return true
end

-- --今天玩游戏次数
-- function User:addPlayGameNum(playerid)	
-- 	local user_info = self:getUserInfo(playerid)
-- 	if user_info then 
-- 		user_info.play_game_round = user_info.play_game_round + 1
-- 		--db_helper.save_user_info(playerid, user_info)
-- 		local data = {playerid=playerid,play_game_round=user_info.play_game_round}
-- 		senddb('update_role',data)
-- 	end
-- end

--安全关服
function User:safeClose()		
	local content = '服务器正在维护,请退出！'
	local data
	for k,v in pairs(self.userList) do
		data =  {nt_kick_player={
			playerid = playerid,
			content = content,
		}}		
		self:notice(v.playerid, data)
	end
	return true
end

--后台对用户属性进行修改
function User:webChangeMoney( playerid, args)
	if not playerid then return false end	
	local status = args.status --状态:0为正常,1永久封停，其他为封停时间戳
	local user_info, user
	
	user = self:getUser(playerid)
	if not user  then
		log.debug("_____由后台对用户属性进行修改_____玩家不在线______")
		return false,0,0 
	end
	--返向更新缓存,从redis拉取
	if not self:setUserInfo(playerid) then 
		return 
	end
	user_info = self:getUserInfo(playerid)

	--封号踢下线	
	if status and status > 0 then 
		self:kickPlayer(playerid)		
		return true
	end

	--金钱发生改变
	local tbGoods = {}
	table.insert(tbGoods,{id = self.tbGoodsName.uchip, num = user_info.uchip })
	table.insert(tbGoods,{id = self.tbGoodsName.udiamond, num = user_info.udiamond})
	if next(tbGoods) then 
		local data = {
			nt_goods_change = {goods=tbGoods}
		}		
		self:notice(playerid,data)
		--把钱变化推送到游戏进程
		self:updateInfoToGame(user, {chip = user_info.uchip, diamond = user_info.udiamond})	
	end
	return true,user_info.uchip,user_info.udiamond
end

--后台对用户属性进行修改
function User:webChangeMoney2( playerid, args)
	if not playerid then return false end	
	local status = args.status --状态:0为正常,1永久封停，其他为封停时间戳
	local user_info, user
	
	user = self:getUser(playerid)
	if not user  then
		log.debug("_____由后台对用户属性进行修改_____玩家不在线______")
		return false,0,0 
	end
	--返向更新缓存,从redis拉取
	if not self:setUserInfo(playerid) then 
		return 
	end
	user_info = self:getUserInfo(playerid)

	--封号踢下线	
	if status and status > 0 then 
		self:kickPlayer(playerid)		
		return true
	end

 	-- $sendArr['uid'] = $uid;
  --   $sendArr['money'] = $money;
  --   $sendArr['code'] = $code;
  --   $sendArr['moneytype'] = $this->type[$type];
  --   $sendArr['moneyFlag'] = $moneyFlag;
  --   $sendArr['msgtype'] = 1;

    local moneyType = args.moneytype
    local moneyFlag = args.moneyFlag
    local money = args.money
    local resMoney = 0
    local data
    local goodName
    if moneyFlag == 0 then 
    	moneyFlag = 1
    elseif moneyFlag == 1 then 
    	moneyFlag = -1
    end
    money = money*moneyFlag
    if moneyType==1 then 
    	resMoney = user_info.uchip + money
    	if resMoney < 0 then 
    		resMoney = 0
    	end
    	user_info.uchip = resMoney
    	data = {uid=playerid,uchip=user_info.uchip}	
    	goodName = "uchip"
    elseif moneyType==2 then 
    	resMoney = user_info.udiamond + money
    	if resMoney < 0 then 
    		resMoney = 0
    	end
    	user_info.udiamond = resMoney
    	data = {uid=playerid,udiamond=user_info.udiamond}    	
    	goodName = "udiamond"
    elseif moneyType==3 then
	
	elseif moneyType==4 then   
    	resMoney = user_info.room_ticket + money
    	if resMoney < 0 then 
    		resMoney = 0
    	end
    	user_info.room_ticket = resMoney
    	data = {uid=playerid,room_ticket=user_info.room_ticket}
    	goodName = "room_ticket"  
	end 	

	--更新到数据库
	if data then 
		senddb('update_role',data,true)	
		--金钱发生改变
		local tbGoods = {}
		table.insert(tbGoods,{id = self.tbGoodsName[goodName], num = user_info[goodName] })
		if next(tbGoods) then 
			local data = {
				nt_goods_change = {goods=tbGoods}
			}		
			self:notice(playerid,data)
			--把钱变化推送到游戏进程
			self:updateInfoToGame(user, {chip = user_info.uchip, diamond = user_info.udiamond})	
		end				
	end
	return true
end


--对机器人属性进行修改
function User:robotChangeMoney( playerid, args)
	print("_____robotChangeMoney___________",args)
	if not playerid then
		return false 
	end	
	local diamond, silver = args.diamond,args.silver
	local user_info, user
	user = self:getUser(playerid)
	log.debug("______对机器人属性进行修改___args___"..playerid .."  "..diamond)
	--更改redis
	local data = {uid=playerid,udiamond=diamond}
	senddb('update_role',data)

	if not user  then
		log.debug("__________玩家不在线______")
		return false
	end
	-- --返向更新缓存,从redis拉取
	-- self:setUserInfo(playerid)
	user_info = self:getUserInfo(playerid)
	--金钱发生改变
	local tbGoods = {}
	if diamond then 
		diamond = user_info.uchip
		table.insert(tbGoods,{id = self.tbGoodsName.uchip, num = tostring(diamond) })
	end
	if silver then 
		silver = user_info.udiamond
		table.insert(tbGoods,{id = self.tbGoodsName.udiamond, num = tostring(silver) })
	end
	if next(tbGoods) then 
		local data = {
			nt_goods_change = {goods=tbGoods}
		}		
		self:notice(playerid,data)
		--把钱变化推送到游戏server
		self:updateInfoToGame(user, {chip =tostring(diamond)})	
	end
	return true
end

---------------------------------------------------------
-- REQUEST
---------------------------------------------------------


function User:test( ... )
	print("______user_test____")
end
return User